package com.ruoyi.hotSpot.task;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.hotSpot.constant.WebSocketConstant;
import com.ruoyi.hotSpot.domain.*;
import com.ruoyi.hotSpot.domain.vo.WebSocketVo;
import com.ruoyi.hotSpot.service.*;
import com.ruoyi.hotSpot.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Author wsl
 * @Date 2025-02-13 9:31
 * @Version 1.0
 */

@Configuration
@EnableScheduling
@Slf4j
public class RegularlyModifyEnableStatusTasks  implements SchedulingConfigurer {

    @Autowired
    private RecordReadingLocationService recordReadingLocationService;



    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private HotSpotRegionService hotSpotRegionService;

    @Autowired
    private DynamicsInfoService dynamicsInfoService;


    @Autowired
    private WebSocketServer webSocketServer;

    @Autowired
    private HotTripNumberService hotTripNumberService;

    //记录闯入闯出
    private static final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap(1024);

    //记录区域内当前有多少目标
    public static final ConcurrentHashMap<Long, HashSet<String>> targetNum = new ConcurrentHashMap<>();

    private static final String ADS = "ADS-";

    private static final String AIS = "AIS-";




    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

//        taskRegistrar.addTriggerTask(
//                () -> this.selectDynamicInfo(),
//                triggerContext -> {
//                    //每日零点执行
//                    String cron = "0/5 * * * * ?";
//                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
//                }
//        );
    }


    public void selectDynamicInfo(){

        System.out.println("---------------------------------------------------------------------------------");
        RecordReadingLocation localtion = recordReadingLocationService.getOne(null);
        //数据库为空时 补全数据
        if(localtion == null){
            localtion = new RecordReadingLocation();
            localtion.setId(1L);
            localtion.setAdsbDynamicInfo(0L);
            localtion.setAisDynamicInfo(0L);
        }
        //获取当前最大数据的id
        Long adsMaxId = dynamicsInfoService.selectMaxId();
        // 查询出需要判断的数据
        QueryWrapper<DynamicsInfo> a2DynamicsInfoQueryWrapper = new QueryWrapper<>();
        a2DynamicsInfoQueryWrapper.select("id", "mmsi_icao", "base_time", "lon", "lat");
        a2DynamicsInfoQueryWrapper.between("id", localtion.getAdsbDynamicInfo(), adsMaxId);
        List<DynamicsInfo> adsList = dynamicsInfoService.list(a2DynamicsInfoQueryWrapper);

        //查询出来的id   根据静态数据库id  将一个飞机的航线分组出来
//        Map<Long, List<AdsbDynamicInfo>> adsMap = adsList.stream().collect(Collectors.groupingBy(AdsbDynamicInfo::getAdsbStaticDataId));

        Map<String, List<DynamicsInfo>> adsMap = adsList.stream()
                .collect(Collectors.groupingBy(
                        DynamicsInfo::getMmsiIcao,
                        Collectors.mapping(
                                Function.identity(),
                                Collectors.collectingAndThen(
                                        Collectors.toList(),
                                        list -> {
                                            list.sort(Comparator.comparing(DynamicsInfo::getBaseTime));
                                            return list;
                                        }
                                )
                        )
                ));

        //把每条航线得点交给线程池去执行
        adsMap.forEach((k, v) -> {
            threadPoolTaskExecutor.execute(() ->{
                //1. 判断点位的状态  在几个区域内
                for (DynamicsInfo adsbDynamicInfo : v) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo(WebSocketConstant.REAL_TIME_TRAJECTORY,adsbDynamicInfo)));
                    Set<String> keySet = map.keySet().stream().filter(key -> key.startsWith(ADS + adsbDynamicInfo.getMmsiIcao())).collect(Collectors.toSet());
                    //判断是否在区域内
                    List<HotSpotRegion> breakOrOut = hotSpotRegionService.isBreakOrOut(adsbDynamicInfo.getLon(), adsbDynamicInfo.getLat(), adsbDynamicInfo.getBaseTime());
                    if(CollectionUtils.isNotEmpty(breakOrOut)){
                        //2. 根据上一个点的状态，判断是不是闯入闯出 然后插入记录数据 更新闯入闯出状态
                        Set<String> cacheSet = new HashSet<>();
                        for (HotSpotRegion hotSpotRegion : breakOrOut) {
                            String key = ADS + adsbDynamicInfo.getMmsiIcao() + "-" + hotSpotRegion.getTaskId();
                            if(map.get(key) == null ||  map.get(key) != 1){

                                HotTripNumber hotTripNumber = new HotTripNumber();
                                hotTripNumber.setTaskId(hotSpotRegion.getTaskId());
                                hotTripNumber.setPointId(adsbDynamicInfo.getId());
                                hotTripNumber.setMmsiIcao(adsbDynamicInfo.getMmsiIcao());
                                hotTripNumber.setBehavior(1);
                                hotTripNumberService.save(hotTripNumber);
                                targetNum.computeIfAbsent(hotSpotRegion.getTaskId(), value -> new HashSet<>()).add(adsbDynamicInfo.getMmsiIcao());
                                Map<String, Object> resultMap = new HashMap<>();
                                resultMap.put("taskId", hotSpotRegion.getTaskId());
                                resultMap.put("size", targetNum.get(hotSpotRegion.getTaskId()).size());
                                webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("HOT", resultMap)));
                                map.put(key, 1);
                            }
                            cacheSet.add(key);
                        }
                        //3. 查询之前存在但是现在不在的区域  修改为闯出
                        keySet.removeAll(cacheSet);

                        if(CollectionUtils.isNotEmpty(keySet)){
                            //todo 闯出
                            keySet.forEach(key ->{
                                if(map.get(key) != null  && map.get(key) == 1){
                                    HotTripNumber hotTripNumber = new HotTripNumber();
                                    String taskID = key.substring(key.lastIndexOf("-") + 1, key.length());
                                    hotTripNumber.setTaskId(Long.valueOf(taskID));
                                    hotTripNumber.setPointId(adsbDynamicInfo.getId());
                                    hotTripNumber.setMmsiIcao(adsbDynamicInfo.getMmsiIcao());
                                    hotTripNumber.setBehavior(2);
                                    hotTripNumberService.save(hotTripNumber);
                                    targetNum.getOrDefault(Long.valueOf(taskID), new HashSet<>()).remove(adsbDynamicInfo.getMmsiIcao());
                                    Map<String, Object> resultMap = new HashMap<>();
                                    resultMap.put("taskId", taskID);
                                    resultMap.put("size", targetNum.get(Long.valueOf(taskID)).size());
                                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("HOT", resultMap)));
                                    map.put(key, 2);
                                }
                            });
                        }
                    } else {
                        //3. 查询之前存在但是现在不在的区域  修改为闯出
                        if(CollectionUtils.isNotEmpty(keySet)){
                            keySet.forEach(key -> {
                                //闯出
                                if(map.get(key) != null  && map.get(key) == 1){

                                    HotTripNumber hotTripNumber = new HotTripNumber();
                                    String taskID = key.substring(key.lastIndexOf("-") + 1, key.length());
                                    hotTripNumber.setTaskId(Long.valueOf(taskID));
                                    hotTripNumber.setPointId(adsbDynamicInfo.getId());
                                    hotTripNumber.setMmsiIcao(adsbDynamicInfo.getMmsiIcao());
                                    hotTripNumber.setBehavior(2);
                                    hotTripNumberService.save(hotTripNumber);
                                    targetNum.getOrDefault(Long.valueOf(taskID), new HashSet<>()).remove(adsbDynamicInfo.getMmsiIcao());
                                    Map<String, Object> resultMap = new HashMap<>();
                                    resultMap.put("taskId", taskID);
                                    resultMap.put("size", targetNum.get(Long.valueOf(taskID)).size());
                                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("HOT", resultMap)));
                                    map.put(key, 2);
                                }
                            });
                        }
                    }
                }
            });
        });


        UpdateWrapper<RecordReadingLocation> wrap = new UpdateWrapper<>();
        wrap.eq("id", localtion.getId());
        wrap.set("adsb_dynamic_info", adsMaxId + 1);
        recordReadingLocationService.update(wrap);
    }


}
